package de.koller.worlders.engine.entity.mo;

import de.koller.oceanFramework.OceanException;
import de.koller.oceanFramework.math.ROVec;
import de.koller.oceanFramework.math.Vec;
import de.koller.oceanFramework.tree.Child;
import de.koller.worlders.engine.entity.AABBObject;
import de.koller.worlders.engine.entity.mo.wphysics.WPTransferObj;
import de.koller.worlders.engine.entity.plattform.Plattform;
import de.koller.worlders.engine.entity.zone.Portal;
import de.koller.worlders.engine.tiles.MOTile;
import de.koller.worlders.render.IGLRender;
import de.koller.worlders.render.visual.DisplayRenderObject;
import java.util.Collections;
import java.util.List;

public class MovingObject extends AABBObject implements IGLRender {

	public static final double GRAVITY = 19.52 * Math.pow( 10, -6 );
	
	public final WPTransferObj wpTransferObj = new WPTransferObj();
	
	private final Vec velocity = new Vec();
	private final Vec energy = new Vec();

	private final Vec moforce = new Vec();
	private Vec sumforce = null;
	
	private boolean bottomContact = false;
	@Child public final MOZoneHandler zoneC = new MOZoneHandler();
	@Child public final MOPlattformHandler plattformHandler = new MOPlattformHandler();
	private boolean death = false;
	private float depth = 1;
	private MOTile moTile = null;
	
	private Portal portalImmune = null;
	public final MOState mostate = new MOState();
	
	public MovingObject( float x, float y, float w, float h ) {
		super( x, y, w, h );
		
//		this.getLight().setDerived( true );
	}

	@Override
	protected void init() {
		super.init();
		
		if( moTile != null )
			moTile.generate( wroot, this );
		
		wroot.rendering.addWorldElement( this );
		//wroot.getEntityContainer().wphysics.addMO( this );
	}

	@Override
	protected void update( int elapsedTime ) {
		super.update( elapsedTime );
		
		sumforce = null;
	}

	@Override
	protected void release() {
		super.release();
		
		if( moTile != null )
			moTile.ungenerate();
		
		wroot.rendering.removeWorldlement( this );
		//wroot.getEntityContainer().wphysics.removeMO( this );
	}
	
	public MovingObject setMOTile( MOTile mot ) {
		if( this.isInitialized() )
			throw new OceanException( "have to be set before init!" );
		
		this.moTile = mot;
		return this;
	}

	@Override
	public void renderGL( int elapsedTime ) {	
		if( moTile == null )
			DisplayRenderObject.renderAABB( this, depth );
		else
			wroot.getTileMap().getMapRendering().renderTile( moTile, depth, false );
	}

	public void impulse( Vec wayBefore, Vec wayAfter, List<Plattform> collision ) {
		Collections.sort( collision );
	
		int usePrio = 0;
		boolean prioUsed = false;
		for( Plattform p : collision ) {
			if( !prioUsed || usePrio <= p.getEffectPriority() ) {
				p.collision( wayBefore, wayAfter, this );
				prioUsed = true;
				usePrio = p.getEffectPriority();
			}
		}
		if( collision.isEmpty() )
			noImpulse();
	}
	
	public void noImpulse() {
		bottomContact = false;
	}
	
	public void moveTo( float x, float y ) {
		this.getEnergy().set( 0, 0 );
		this.getPosition().set( x, y );
	}

	public Vec getEnergy() {
		return energy;
	}

	public Vec getVelocity() {
		return velocity;
	}

	public Vec getSelfForce() {
		return moforce;
	}
	
	
	public ROVec getForce() {
		if( sumforce == null ) {
			ROVec wf = wroot.getEntityContainer().getWorldForce( this );
			sumforce = new Vec( moforce.getX() + wf.getX(),
								moforce.getY() + wf.getY() );
		}
		
		return sumforce;
	}

	public boolean isBottomContact() {
		return bottomContact;
	}

	public void setBottomContact( boolean bottomContact ) {
		this.bottomContact = bottomContact;
	}

	public boolean isDeath() {
		return death;
	}

	public void setDeath( boolean death ) {
		this.death = death;
	}

	public void setDepth( float depth ) {
		this.depth = depth;
	}

	public MOTile getMoTile() {
		return moTile;
	}

	public Portal getPortalImmune() {
		return portalImmune;
	}

	public void setPortalImmune( Portal portalImmune ) {
		this.portalImmune = portalImmune;
	}

}
